/*!
 * \file cosecha.cpp
 *
 * \date Sep 29, 2014
 * \author correa
 */

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <list>
#include <limits>
#include <algorithm>

#include <dirent.h>
#include <sys/types.h>

using namespace std;

typedef struct {
	int nvert;
	double dens;
	int omegamin;
	int omegamax;
} Tamanos;

typedef struct {
	string nombre;
	Tamanos tamanos;
} Instance;

bool dimacsNombreComp(Instance lhs, Instance rhs) {
	string lnombre(lhs.nombre), rnombre(rhs.nombre);
	transform(lhs.nombre.begin(), lhs.nombre.end(), lnombre.begin(), ::tolower);
	transform(rhs.nombre.begin(), rhs.nombre.end(), rnombre.begin(), ::tolower);

	if (lnombre == rnombre)
		return lhs.tamanos.nvert < rhs.tamanos.nvert;

	return lnombre < rnombre;
}

bool randNombreComp(Instance lhs, Instance rhs) {
	if (lhs.tamanos.nvert != rhs.tamanos.nvert)
		return lhs.tamanos.nvert < rhs.tamanos.nvert;

	return lhs.nombre < rhs.nombre;
}

bool dimacsDensComp(Instance lhs, Instance rhs) {
	if (lhs.tamanos.dens == rhs.tamanos.dens)
		return dimacsNombreComp(lhs, rhs);

	return lhs.tamanos.dens < rhs.tamanos.dens;
}

bool randDensComp(Instance lhs, Instance rhs) {
	if (lhs.tamanos.dens == rhs.tamanos.dens)
		return randNombreComp(lhs, rhs);

	return lhs.tamanos.dens < rhs.tamanos.dens;
}

map<string, Tamanos> conocidasDimacs {
	{ "brock200_1", { 200, 0.75, 21, 21 } },
	{ "brock200_2",	{ 200, 0.49, 12, 12 } },
	{ "brock200_3", { 200, 0.49, 15, 15 } },
	{ "brock200_4", { 200, 0.65, 17, 17 } },
	{ "brock400_1", { 400, 0.75, 27, 27 } },
	{ "brock400_2", { 400, 0.75, 29, 29 } },
	{ "brock400_3", { 400, 0.75, 31, 31 } },
	{ "brock400_4", { 400, 0.75, 33, 33 } },
	{ "brock800_1", { 800, 0.65, 23, 23 } },
	{ "brock800_2", { 800, 0.65, 24, 24 } },
	{ "brock800_3", { 800, 0.65, 25, 25 } },
	{ "brock800_4", { 800, 0.65, 26, 26 } },
	{ "c-fat500-1", { 500, 0.036, 14, 14 } },
	{ "c-fat500-2", { 500, 0.073, 26, 26 } },
	{ "c-fat500-5", { 500, 0.186, 64, 64 } },
	{ "c-fat500-10", { 500, 0.374, 126, 126 } },
	{ "C125.9", { 125, 0.90, 34, 34 } },
	{ "C250.9", { 250, 0.90, 44, 44 } },
	{ "DSJC500.5", { 500, 0.50, 13, 13 } },
	{ "DSJC1000.5", { 1000, 0.50, 15, 15 } },
	{ "frb30-15-1", { 450, 0.82, 30, 30 } },
	{ "frb30-15-2", { 450, 0.82, 30, 30 } },
	{ "frb30-15-3", { 450, 0.82, 30, 30 } },
	{ "frb30-15-4", { 450, 0.82, 30, 30 } },
	{ "frb30-15-5", { 450, 0.82, 30, 30 } },
	{ "gen200_p0.9_44", { 200, 0.90, 44, 44 } },
	{ "gen200_p0.9_55", { 200, 0.90, 55, 55 } },
	{ "hamming8-4", { 256, 0.64, 16, 16 } },
	{ "keller4", { 171, 0.65, 11, 11 } },
	{ "MANN_a27", { 378, 0.99, 126, 126 } },
	{ "MANN_a45", { 1035, 1.00, 345, 345 } },
	{ "p_hat300-1", { 300, 0.24, 8, 8 } },
	{ "p_hat300-2", { 300, 0.49, 25, 25 } },
	{ "p_hat300-3", { 300, 0.74, 36, 36 } },
	{ "p_hat700-1", { 700, 0.25, 11, 11 } },
	{ "p_hat700-2", { 700, 0.50, 44, 44 } },
	{ "p_hat700-3", { 700, 0.75, 62, 62 } },
	{ "p_hat1000-1", { 1000, 0.245, 10, 10 } },
	{ "p_hat1000-2", { 1000, 0.49, 46, 46 } },
	{ "p_hat1500-1", { 1500, 0.253, 12, 12 } },
	{ "san200_0.7_2", { 200, 0.70, 18, 18 } },
	{ "san200_0.9_1", { 200, 0.90, 70, 70 } },
	{ "san200_0.9_2", { 200, 0.90, 60, 60 } },
	{ "san200_0.9_3", { 200, 0.90, 44, 44 } },
	{ "san400_0.5_1", { 400, 0.50, 13, 13 } },
	{ "san400_0.9_1", { 400, 0.90, 100, 100 } },
	{ "sanr200_0.7", { 200, 0.69, 18, 18 } },
	{ "sanr200_0.9", { 200, 0.89, 42, 42 } },
	{ "sanr400_0.5", { 400, 0.50, 13, 13 } },
	{ "sanr400_0.7", { 400, 0.70, 21, 21 } }
};

map<string, Tamanos> conocidasTomitaMCS {
	{ "200_80", { 200, 0.8, 24, 27 } },
	{ "200_90", { 200, 0.9, 40, 44 } },
	{ "200_95", { 200, 0.95, 58, 66 } },
	{ "200_98", { 200, 0.98, 90, 103 } },
	{ "300_70", { 300, 0.7, 19, 21 } },
	{ "300_80", { 300, 0.8, 28, 29 } },
	{ "500_50", { 500, 0.5, 13, 14 } },
	{ "500_60", { 500, 0.6, 17, 17 } },
	{ "500_70", { 500, 0.7, 22, 23 } },
	{ "1000_40", { 1000, 0.4, 12, 12 } },
	{ "1000_50", { 1000, 0.5, 15, 15 } },
	{ "5000_10", { 5000, 0.1, 7, 7 } },
	{ "5000_20", { 5000, 0.2, 9, 9 } },
	{ "5000_30", { 5000, 0.3, 12, 12 } },
	{ "10000_10", { 10000, 0.1, 7, 8 } },
	{ "15000_10", { 15000, 0.1, 8, 8 } }
};

map<string, Tamanos> conocidasSegundoJimenez {
	{ "200_70", { 200, 0.7, 17, 18 } },
	{ "200_80", { 200, 0.8, 25, 26 } },
	{ "200_90", { 200, 0.9, 40, 42 } },
	{ "200_95", { 200, 0.95, 61, 64 } },
	{ "300_70", { 300, 0.7, 20, 21 } },
	{ "300_80", { 300, 0.8, 28, 29 } },
	{ "500_50", { 500, 0.5, 13, 13 } },
	{ "500_60", { 500, 0.6, 17, 17 } },
	{ "1000_10", { 1000, 0.1, 5, 6 } },
	{ "1000_20", { 1000, 0.2, 7, 8 } },
	{ "1000_30", { 1000, 0.3, 9, 10 } },
	{ "1000_40", { 1000, 0.4, 12, 12 } },
	{ "1000_50", { 1000, 0.5, 14, 15 } },
	{ "5000_10", { 5000, 0.1, 7, 7 } },
	{ "5000_20", { 5000, 0.2, 9, 10 } },
	{ "10000_10", { 10000, 0.1, 7, 8 } },
	{ "15000_10", { 15000, 0.1, 8, 8 } }
};

map<string, Tamanos> conocidasSegundoMatia {
	{ "200_70", { 200, 0.7, 17, 18 } },
	{ "200_80", { 200, 0.8, 25, 26 } },
	{ "200_90", { 200, 0.9, 40, 42 } },
	{ "200_95", { 200, 0.95, 61, 64 } },
	{ "300_70", { 300, 0.7, 20, 21 } },
	{ "300_80", { 300, 0.8, 28, 29 } },
	{ "300_98", { 300, 0.98, 116, 127 } },
	{ "500_50", { 500, 0.5, 13, 13 } },
	{ "500_60", { 500, 0.6, 17, 17 } },
	{ "500_70", { 500, 0.7, 22, 23 } },
	{ "500_994", { 500, 0.994, 261, 276 } },
	{ "1000_10", { 1000, 0.1, 5, 6 } },
	{ "1000_20", { 1000, 0.2, 7, 8 } },
	{ "1000_30", { 1000, 0.3, 9, 10 } },
	{ "1000_40", { 1000, 0.4, 12, 12 } },
	{ "1000_50", { 1000, 0.5, 14, 15 } },
	{ "1000_998", { 1000, 0.998, 591, 618 } },
	{ "5000_10", { 5000, 0.1, 7, 7 } },
	{ "5000_20", { 5000, 0.2, 9, 10 } },
	{ "10000_10", { 10000, 0.1, 7, 8 } },
	{ "15000_10", { 15000, 0.1, 8, 8 } }
};

class Corrida {
public:
	int npruebas;
	double renumbTime;
	double compTime;
	double nsubp;

	Corrida() :
			npruebas(0), renumbTime(0), compTime(0), nsubp(0) {
	}
	;
	Corrida(int np, double rt, double ct, double ns) :
			npruebas(np), renumbTime(rt), compTime(ct), nsubp(ns) {
	}
	;
	Corrida(int np, double ct, double ns) :
			npruebas(np), renumbTime(0), compTime(ct), nsubp(ns) {
	}
	;

	Corrida(string datos);
	void accumulate(string datos);
	void promedio();

	void print(Instance graph, int K);
};

typedef map<Instance, vector<vector<Corrida> >, bool (*)(Instance, Instance)> mapCorridas;

map<string, Corrida> tomitaMCS {
	{ "brock400_1", Corrida(1, 693, -1) },
	{ "brock400_2", Corrida(1, 297, -1) },
	{ "brock400_3", Corrida(1, 468, -1) },
	{ "brock400_4", Corrida(1, 248,	-1) },
	{ "brock800_1", Corrida(1, 9347, -1) },
	{ "brock800_2",	Corrida(1, 8368, -1) },
	{ "brock800_3", Corrida(1, 5755, -1) },
	{ "brock800_4", Corrida(1, 3997, -1) },
	{ "C250.9", Corrida(1, 3257, -1) },
	{ "MANN_a27", Corrida(1, 0.8, -1) },
	{ "MANN_a45", Corrida(1, 281, 225000) },
	{ "p_hat300-3", Corrida(1, 2.5,	-1) },
	{ "p_hat500-2", Corrida(1, 0.7, -1) },
	{ "p_hat500-3",	Corrida(1, 150, 7923000) },
	{ "p_hat700-2", Corrida(1, 5.6, -1) },
	{ "p_hat700-3", Corrida(1, 2392, 88168000) },
	{ "p_hat1000-2", Corrida(1, 221, -1) },
	{ "p_hat1500-2", Corrida(1, 16512, -1) },
	{ "san200_0.9_1", Corrida(1, 0.22, -1) },
	{ "san200_0.9_2", Corrida(1, 0.4, -1) },
	{ "san400_0.7_1", Corrida(1, 0.54, -1) },
	{ "san400_0.7_2", Corrida(1, 0.13, -1) },
	{ "san400_0.7_3", Corrida(1, 1.4, -1) },
	{ "san400_0.9_1", Corrida(1, 0.1, 2000) },
	{ "san1000", Corrida(1,	2.1, -1) },
	{ "sanr200_0.7", Corrida(1, 0.34, -1) },
	{ "sanr200_0.9", Corrida(1, 41, -1) },
	{ "sanr400_0.7", Corrida(1, 181, -1) },
	{ "gen200_p0.9_44", Corrida(1, 0.47, 35000) },
	{ "gen200_p0.9_55", Corrida(1, 1.2, 112000) },
	{ "gen400_p0.9_55",	Corrida(1, 58431, 2894935000) },
	{ "gen400_p0.9_65", Corrida(1, 151597, 3332982000) },
	{ "gen400_p0.9_75", Corrida(1, 294175, -1) },
	{ "100_80", Corrida(1, 0.008, -1) },
	{ "100_90", Corrida(1, 0.013, -1) },
	{ "100_95", Corrida(1, 0.003, -1) },
	{ "100_98", Corrida(1, 0.0009, -1) },
	{ "150_80", Corrida(1, 0.23, -1) },
	{ "150_90", Corrida(1, 1.00, -1) },
	{ "150_95", Corrida(1, 0.35, -1) },
	{ "150_98", Corrida(1, 0.006, -1) },
	{ "200_80",	Corrida(1, 4.5, -1) },
	{ "200_90", Corrida(1, 74, 6608000) },
	{ "200_95", Corrida(1, 59, 2735000) },
	{ "200_98", Corrida(1, 0.2,	4000) },
	{ "300_60", Corrida(1, 1.0, -1) },
	{ "300_70", Corrida(1, 12, -1) },
	{ "300_80", Corrida(1, 394, -1) },
	{ "300_90",	Corrida(1, 62607, -1) },
	{ "300_98", Corrida(1, 2623, 31619000) },
	{ "500_50", Corrida(1, 2.8,	-1) },
	{ "500_60", Corrida(1, 40, -1) },
	{ "500_70", Corrida(1, 1539, -1) },
	{ "500_994", Corrida(1, 39, 70000) },
	{ "1000_40", Corrida(1, 13.2, -1) },
	{ "1000_50", Corrida(1, 290, -1) },
	{ "1000_60", Corrida(1, 15317, -1) },
	{ "1000_66", Corrida(1,	275964, -1) },
	{ "1000_998", Corrida(1, 46, -1) },
	{ "2000_9995", Corrida(1, 61, -1) },
	{ "5000_10", Corrida(1, 3.3, -1) },
	{ "5000_20", Corrida(1, 138, -1) },
	{ "5000_30", Corrida(1, 5818, -1) },
	{ "10000_10", Corrida(1, 60, -1) },
	{ "10000_20", Corrida(1, 4389, -1) },
	{ "15000_10", Corrida(1, 327, -1) },
	{ "20000_10", Corrida(1, 1179, -1) } };

map<string, Corrida> segundoJimenez {
	{ "brock200_1", Corrida(1, 0.5, 295754) },
	{ "brock200_3", Corrida(1, 0.015, 13534) },
	{ "brock200_4", Corrida(1, 0.078, 64676) },
	{ "brock400_1", Corrida(1, 502.796, 168767856) },
	{ "brock400_2",	Corrida(1, 211.218, 66381296) },
	{ "brock400_3", Corrida(1, 336.188, 118561387) },
	{ "brock400_4", Corrida(1, 200.187,	66669902) },
	{ "brock800_1", Corrida(1, 8600.125, 1926926638) },
	{ "brock800_2", Corrida(1, 7851.875, 1746564619) },
	{ "brock800_3",	Corrida(1, 5063.203, 1100063466) },
	{ "brock800_4", Corrida(1, 3573.328, 730565420) },
	{ "c-fat500-5", Corrida(1, 0.016, 620) },
	{ "c-fat500-10", Corrida(1,	0.031, 744) },
	{ "hamming8-2", Corrida(1, 0.031, 255) },
	{ "hamming8-4", Corrida(1, 0.031, 20313) },
	{ "hamming10-2", Corrida(1, 0.187, 1023) },
	{ "keller4", Corrida(1, 0.016, 12105) },
	{ "MANN_a27", Corrida(1, 0.547,	38253) },
	{ "MANN_a45", Corrida(1, 242.594, 2953135) },
	{ "p_hat300-2", Corrida(1, 0.031, 6226) },
	{ "p_hat300-3",	Corrida(1, 1.922, 590226) },
	{ "p_hat500-1", Corrida(1, 0.032, 10179) },
	{ "p_hat500-2", Corrida(1, 0.609, 126265) },
	{ "p_hat500-3", Corrida(1, 127.469, 18570532) },
	{ "p_hat700-1",	Corrida(1, 0.078, 30253) },
	{ "p_hat700-2", Corrida(1, 5.468, 714868) },
	{ "p_hat700-3", Corrida(1, 2719.328, 247991612) },
	{ "p_hat1000-2", Corrida(1, 272.578, 25693768) },
	{ "p_hat1500-1", Corrida(1, 4.421, 1086747) },
	{ "san200_0.7_1", Corrida(1, 0.016, 3512) },
	{ "san200_0.7_2", Corrida(1, 0.016, 1346) },
	{ "san200_0.9_1", Corrida(1, 0.296, 110813) },
	{ "san200_0.9_2", Corrida(1, 0.188, 62766) },
	{ "san200_0.9_3", Corrida(1, 0.047,	13206) },
	{ "san400_0.5_1", Corrida(1, 0.016, 3927) },
	{ "san400_0.7_1", Corrida(1, 0.359, 78936) },
	{ "san400_0.7_2", Corrida(1, 0.141, 39050) },
	{ "san400_0.7_3", Corrida(1, 0.766,	241902) },
	{ "san400_0.9_1", Corrida(1, 0.234, 20627) },
	{ "san1000", Corrida(1, 0.875, 88286) },
	{ "sanr200_0.7", Corrida(1, 0.187, 130864) },
	{ "sanr200_0.9", Corrida(1, 27.797,	9585825) },
	{ "sanr400_0.5", Corrida(1, 0.437, 257244) },
	{ "sanr400_0.7", Corrida(1, 133.578, 54279188) },
	{ "100_60",	Corrida(1, 0.006, 876) },
	{ "100_70", Corrida(1, 0.003, 1806) },
	{ "100_80", Corrida(1, 0.010, 4595) },
	{ "100_90", Corrida(1, 0.016, 7378) },
	{ "100_95", Corrida(1, 0.016, 1339) },
	{ "150_50",	Corrida(1, 0.006, 1929) },
	{ "150_60", Corrida(1, 0.006, 5255) },
	{ "150_70", Corrida(1, 0.028, 21969) },
	{ "150_80", Corrida(1, 0.178, 110378) },
	{ "150_90",	Corrida(1, 0.984, 409727) },
	{ "150_95", Corrida(1, 0.212, 61390) },
	{ "200_40", Corrida(1, 0.003, 2053) },
	{ "200_50",	Corrida(1, 0.009, 7159) },
	{ "200_60", Corrida(1, 0.047, 35550) },
	{ "200_70", Corrida(1, 0.250, 169819) },
	{ "200_80", Corrida(1, 3.594, 2003197) },
	{ "200_90",	Corrida(1, 56.597, 19534465) },
	{ "200_95", Corrida(1, 59.619, 14505493) },
	{ "300_40", Corrida(1, 0.016, 9992) },
	{ "300_50",	Corrida(1, 0.066, 47126) },
	{ "300_60", Corrida(1, 0.491, 328398) },
	{ "300_70", Corrida(1, 7.647, 4170171) },
	{ "300_80",	Corrida(1, 254.706, 102087337) },
	{ "500_30", Corrida(1, 0.031, 19831) },
	{ "500_40", Corrida(1, 0.206, 120074) },
	{ "500_50",	Corrida(1, 1.906, 975599) },
	{ "500_60", Corrida(1, 27.669, 11423696) },
	{ "1000_10", Corrida(1, 0.008, 3995) },
	{ "1000_20", Corrida(1, 0.091, 38641) },
	{ "1000_30", Corrida(1,	0.931, 393404) },
	{ "1000_40", Corrida(1, 11.325, 3731481) },
	{ "1000_50", Corrida(1, 267.344, 74347239) },
	{ "3000_10", Corrida(1, 0.644, 151874) },
	{ "3000_20", Corrida(1, 10.985,	2744195) },
	{ "3000_20", Corrida(1, 312.744, 71098053) },
	{ "5000_10", Corrida(1, 4.409, 533968) },
	{ "5000_20", Corrida(1,	165.091, 30887512) },
	{ "10000_10", Corrida(1, 93.053, 5541681) },
	{ "15000_10", Corrida(1, 410.697, 21419998) } };

map<string, Corrida> segundoTapiaI {
	{ "brock200_1", Corrida(1, -1, 93100) },
	{ "brock400_1", Corrida(1, -1, 46984200) },
	{ "brock400_2", Corrida(1, -1, 17854200) },
	{ "brock400_3", Corrida(1, -1, 34034300) },
	{ "brock400_4", Corrida(1, -1, 18456500) },
	{ "brock800_1", Corrida(1, -1, 423852600) },
	{ "brock800_2", Corrida(1, -1, 385559800) },
	{ "brock800_3", Corrida(1, -1, 233969600) },
	{ "brock800_4", Corrida(1, -1, 148615500) },
	{ "MANN_a27", Corrida(1, -1, 18300) },
	{ "MANN_a45", Corrida(1, -1, 1081000) },
	{ "p_hat300-3", Corrida(1, -1, 176700) },
	{ "p_hat500-2",	Corrida(1, -1, 30900) },
	{ "p_hat500-3", Corrida(1, -1, 5052800) },
	{ "p_hat700-2", Corrida(1, -1, 176600) },
	{ "p_hat700-3", Corrida(1, -1, 58764000) },
	{ "p_hat1000-1", Corrida(1, -1, 36000) },
	{ "p_hat1000-2", Corrida(1, -1, 61915000) },
	{ "p_hat1500-1", Corrida(1, -1, 143800) },
	{ "san200_0.9_2", Corrida(1, -1, 6200) },
	{ "san400_0.7_1", Corrida(1, -1, 18100) },
	{ "san400_0.7_3", Corrida(1, -1, 40900) },
	{ "san400_0.9_1", Corrida(1, -1, 6300) },
	{ "san1000", Corrida(1, -1, 8600) },
	{ "sanr200_0.7", Corrida(1, -1, 40100) },
	{ "sanr200_0.9", Corrida(1, -1, 3496500) },
	{ "sanr400_0.5", Corrida(1, -1, 60300) },
	{ "sanr400_0.7", Corrida(1, -1, 15226300) },
	{ "gen200_p0.9_44", Corrida(1, -1, 56300) },
	{ "gen200_p0.9_55", Corrida(1, -1, 109500) },
	{ "C250.9", Corrida(1, -1, 309822800) },
	{ "frb30-15-1", Corrida(1, -1, 256131700) },
	{ "frb30-15-2", Corrida(1, -1, 159314100) },
	{ "frb30-15-3", Corrida(1, -1, 99025400) },
	{ "frb30-15-4", Corrida(1, -1, 302448800) },
	{ "frb30-15-5", Corrida(1, -1, 207658100) },
	{ "DSJC500.5", Corrida(1, -1, 262200) },
	{ "DSJC1000.5", Corrida(1, -1, 15251600) },
	{ "150_90", Corrida(1, -1, 140200) },
	{ "150_95", Corrida(1, -1, 33500) },
	{ "200_70", Corrida(1, -1, 45900) },
	{ "200_80", Corrida(1, -1, 502900) },
	{ "200_90", Corrida(1, -1, 6985700) },
	{ "200_95", Corrida(1, -1, 13470800) },
	{ "200_98", Corrida(1, -1, 41100) },
	{ "300_60",	Corrida(1, -1, 96600) },
	{ "300_70", Corrida(1, -1, 1150600) },
	{ "300_80", Corrida(1, -1, 38276200) },
	{ "500_40", Corrida(1, -1, 25200) },
	{ "500_50", Corrida(1, -1, 199800) },
	{ "500_60", Corrida(1, -1, 3013000) },
	{ "500_70", Corrida(1, -1, 128779600) },
	{ "1000_30", Corrida(1, -1, 52600) },
	{ "1000_40", Corrida(1, -1, 713700) },
	{ "1000_50", Corrida(1, -1, 15129500) },
	{ "5000_10", Corrida(1, -1, 16200) },
	{ "5000_20", Corrida(1, -1, 1650400) },
	{ "10000_10", Corrida(1, -1, 776900) },
	{ "15000_10", Corrida(1, -1, 2584900) } };

map<string, Corrida> segundoTapiaR {
	{ "brock200_1", Corrida(1, -1, 52600) },
	{ "brock400_1", Corrida(1, -1, 26230800) },
	{ "brock400_2", Corrida(1, -1, 10107100) },
	{ "brock400_3", Corrida(1, -1, 19254800) },
	{ "brock400_4", Corrida(1, -1, 11110600) },
	{ "brock800_1", Corrida(1, -1, 250658200) },
	{ "brock800_2", Corrida(1, -1, 227932200) },
	{ "brock800_3", Corrida(1, -1, 142784100) },
	{ "brock800_4", Corrida(1, -1, 93455500) },
	{ "MANN_a27", Corrida(1, -1, 7500) },
	{ "MANN_a45", Corrida(1, -1, 240200) },
	{ "p_hat300-3", Corrida(1, -1, 101300) },
	{ "p_hat500-2",	Corrida(1, -1, 17300) },
	{ "p_hat500-3", Corrida(1, -1, 2568900) },
	{ "p_hat700-2", Corrida(1, -1, 96700) },
	{ "p_hat700-3", Corrida(1, -1, 29459700) },
	{ "p_hat1000-1", Corrida(1, -1, 28800) },
	{ "p_hat1000-2", Corrida(1, -1, 3305400) },
	{ "p_hat1500-1", Corrida(1, -1, 128200) },
	{ "san200_0.9_2", Corrida(1, -1, 53100) },
	{ "san400_0.7_1", Corrida(1, -1, 10500) },
	{ "san400_0.7_3", Corrida(1, -1, 46400) },
	{ "san400_0.9_1", Corrida(1, -1, 3005900) },
	{ "san1000", Corrida(1, -1, 5600) },
	{ "sanr200_0.7", Corrida(1, -1, 24200) },
	{ "sanr200_0.9", Corrida(1, -1, 1546900) },
	{ "sanr400_0.5", Corrida(1, -1, 38300) },
	{ "sanr400_0.7", Corrida(1, -1, 9016900) },
	{ "gen200_p0.9_44", Corrida(1, -1, 42300) },
	{ "gen200_p0.9_55", Corrida(1, -1, 74800) },
	{ "C250.9", Corrida(1, -1, 136417800) },
	{ "frb30-15-1", Corrida(1, -1, 174364800) },
	{ "frb30-15-2", Corrida(1, -1, 116173500) },
	{ "frb30-15-3", Corrida(1, -1, 62870400) },
	{ "frb30-15-4", Corrida(1, -1, 195782100) },
	{ "frb30-15-5", Corrida(1, -1, 134849800) },
	{ "DSJC500.5", Corrida(1, -1, 175900) },
	{ "DSJC1000.5", Corrida(1, -1, 9437800) },
	{ "150_90", Corrida(1, -1, 71900) },
	{ "150_95", Corrida(1, -1, 18200) },
	{ "200_70", Corrida(1, -1, 27900) },
	{ "200_80", Corrida(1, -1, 275500) },
	{ "200_90", Corrida(1, -1, 3251400) },
	{ "200_95", Corrida(1, -1, 6401900) },
	{ "200_98", Corrida(1, -1, 23500) },
	{ "300_60",	Corrida(1, -1, 62700) },
	{ "300_70", Corrida(1, -1, 684800) },
	{ "300_80", Corrida(1, -1, 20355500) },
	{ "500_40", Corrida(1, -1, 17800) },
	{ "500_50", Corrida(1, -1, 130600) },
	{ "500_60", Corrida(1, -1, 1864700) },
	{ "500_70", Corrida(1, -1, 76028900) },
	{ "1000_30", Corrida(1, -1, 42100) },
	{ "1000_40", Corrida(1, -1, 441900) },
	{ "1000_50", Corrida(1, -1, 9372700) },
	{ "5000_10", Corrida(1, -1, 8200) },
	{ "5000_20", Corrida(1, -1, 1324200) },
	{ "10000_10", Corrida(1, -1, 470400) },
	{ "15000_10", Corrida(1, -1, 1840000) } };

map<string, Corrida> segundoMatiaI { { "brock200_1", Corrida(1, 0.327, -1) }, {
		"brock200_4", Corrida(1, 0.062, -1) }, { "brock400_1", Corrida(1, 341,
		-1) }, { "brock400_2", Corrida(1, 144, -1) }, { "brock400_3", Corrida(1,
		229, -1) }, { "brock400_4", Corrida(1, 133.4, -1) }, { "hamming8-4",
		Corrida(1, 0.032, -1) }, { "hamming10-2", Corrida(1, 0.031, -1) }, {
		"keller4", Corrida(1, 0.016, -1) },
		{ "MANN_a27", Corrida(1, 0.312, -1) },
		{ "MANN_a45", Corrida(1, 144, -1) }, { "p_hat300-2", Corrida(1, 0.015,
				-1) }, { "p_hat300-3", Corrida(1, 1.25, -1) }, { "p_hat500-2",
				Corrida(1, 0.39, -1) }, { "p_hat500-3", Corrida(1, 73.9, -1) },
		{ "p_hat700-1", Corrida(1, 0.047, -1) }, { "p_hat700-2", Corrida(1,
				3.51, -1) }, { "p_hat700-3", Corrida(1, 1720, -1) }, {
				"p_hat1000-1", Corrida(1, 0.328, -1) }, { "p_hat1000-2",
				Corrida(1, 187, -1) }, { "p_hat1500-1", Corrida(1, 3.23, -1) },
		{ "san200_0.9_1", Corrida(1, 0.156, -1) }, { "san200_0.9_2", Corrida(1,
				0.109, -1) }, { "san200_0.9_3", Corrida(1, 0.015, -1) }, {
				"san400_0.5_1", Corrida(1, 0.016, -1) }, { "san400_0.7_1",
				Corrida(1, 0.234, -1) },
		{ "san400_0.7_2", Corrida(1, 0.078, -1) }, { "san400_0.7_3", Corrida(1,
				0.514, -1) }, { "san400_0.9_1", Corrida(1, 0.141, -1) }, {
				"san1000", Corrida(1, 0.686, -1) }, { "sanr200_0.7", Corrida(1,
				0.125, -1) }, { "sanr200_0.9", Corrida(1, 18.20, -1) }, {
				"sanr400_0.5", Corrida(1, 0.297, -1) }, { "sanr400_0.7",
				Corrida(1, 91, -1) },
		{ "gen200_p0.9_44", Corrida(1, 0.328, -1) }, { "gen200_p0.9_55",
				Corrida(1, 0.546, -1) }, { "C125.9", Corrida(1, 0.031, -1) }, {
				"C250.9", Corrida(1, 1650, -1) }, { "100_70", Corrida(1, 0.002,
				-1) }, { "100_80", Corrida(1, 0.005, -1) }, { "100_90", Corrida(
				1, 0.003, -1) }, { "100_95", Corrida(1, 0.002, -1) }, {
				"150_60", Corrida(1, 0.008, -1) }, { "150_70", Corrida(1, 0.015,
				-1) }, { "150_80", Corrida(1, 0.091, -1) }, { "150_90", Corrida(
				1, 0.51, -1) }, { "150_95", Corrida(1, 0.129, -1) }, { "150_98",
				Corrida(1, 0.005, -1) }, { "200_60", Corrida(1, 0.022, -1) }, {
				"200_70", Corrida(1, 0.155, -1) }, { "200_80", Corrida(1, 1.66,
				-1) }, { "200_90", Corrida(1, 33.40, -1) }, { "200_95", Corrida(
				1, 29, -1) }, { "200_98", Corrida(1, 0.292, -1) }, { "300_60",
				Corrida(1, 0.32, -1) }, { "300_70", Corrida(1, 4.27, -1) }, {
				"300_80", Corrida(1, 205, -1) }, { "500_50", Corrida(1, 1.24,
				-1) }, { "500_60", Corrida(1, 17.9, -1) }, { "500_70", Corrida(
				1, 956, -1) }, { "1000_10", Corrida(1, 0.006, -1) }, {
				"1000_20", Corrida(1, 0.062, -1) }, { "1000_30", Corrida(1,
				0.627, -1) }, { "1000_40", Corrida(1, 7.33, -1) }, { "1000_50",
				Corrida(1, 174.1, -1) }, { "5000_10", Corrida(1, 1.580, -1) }, {
				"5000_20", Corrida(1, 70.35, -1) }, { "10000_10", Corrida(1,
				27.5, -1) }, { "15000_10", Corrida(1, 148, -1) } };

map<string, Corrida> segundoMatiaR { { "brock200_1", Corrida(1, 0.312, -1) }, {
		"brock200_4", Corrida(1, 0.063, -1) }, { "brock400_1", Corrida(1, 348,
		-1) }, { "brock400_2", Corrida(1, 140, -1) }, { "brock400_3", Corrida(1,
		240, -1) }, { "brock400_4", Corrida(1, 143, -1) }, { "hamming8-4",
		Corrida(1, 0.015, -1) }, { "hamming10-2", Corrida(1, 0.063, -1) }, {
		"MANN_a27", Corrida(1, 0.187, -1) },
		{ "MANN_a45", Corrida(1, 42.40, -1) }, { "p_hat300-3", Corrida(1, 1.31,
				-1) }, { "p_hat500-2", Corrida(1, 0.39, -1) }, { "p_hat500-3",
				Corrida(1, 76.1, -1) }, { "p_hat700-1", Corrida(1, 0.047, -1) },
		{ "p_hat700-2", Corrida(1, 3.79, -1) }, { "p_hat700-3", Corrida(1, 1640,
				-1) }, { "p_hat1000-1", Corrida(1, 0.421, -1) }, {
				"p_hat1000-2", Corrida(1, 193, -1) }, { "p_hat1500-1", Corrida(
				1, 3.92, -1) }, { "san200_0.9_1", Corrida(1, 0.094, -1) }, {
				"san200_0.9_2", Corrida(1, 0.062, -1) }, { "san200_0.9_3",
				Corrida(1, 0.015, -1) },
		{ "san400_0.5_1", Corrida(1, 0.016, -1) }, { "san400_0.7_1", Corrida(1,
				0.125, -1) }, { "san400_0.7_2", Corrida(1, 0.063, -1) }, {
				"san400_0.7_3", Corrida(1, 0.437, -1) }, { "san400_0.9_1",
				Corrida(1, 0.031, -1) }, { "san1000", Corrida(1, 0.375, -1) }, {
				"sanr200_0.7", Corrida(1, 0.125, -1) }, { "sanr200_0.9",
				Corrida(1, 13.90, -1) },
		{ "sanr400_0.5", Corrida(1, 0.327, -1) }, { "sanr400_0.7", Corrida(1,
				102, -1) }, { "gen200_p0.9_44", Corrida(1, 0.187, -1) }, {
				"gen200_p0.9_55", Corrida(1, 0.437, -1) }, { "C125.9", Corrida(
				1, 0.016, -1) }, { "C250.9", Corrida(1, 1290, -1) }, { "100_70",
				Corrida(1, 0.0032, -1) }, { "100_80", Corrida(1, 0.002, -1) }, {
				"100_90", Corrida(1, 0.003, -1) }, { "150_70", Corrida(1, 0.016,
				-1) }, { "150_80", Corrida(1, 0.081, -1) }, { "150_90", Corrida(
				1, 0.429, -1) }, { "150_95", Corrida(1, 0.091, -1) }, {
				"200_60", Corrida(1, 0.025, -1) }, { "200_70", Corrida(1, 0.155,
				-1) }, { "200_80", Corrida(1, 1.58, -1) }, { "200_90", Corrida(
				1, 27.10, -1) }, { "200_95", Corrida(1, 18.70, -1) }, {
				"200_98", Corrida(1, 0.232, -1) }, { "300_60", Corrida(1, 0.351,
				-1) }, { "300_70", Corrida(1, 4.66, -1) }, { "300_80", Corrida(
				1, 196, -1) }, { "500_50", Corrida(1, 1.29, -1) }, { "500_60",
				Corrida(1, 19.9, -1) }, { "500_70", Corrida(1, 919, -1) }, {
				"1000_10", Corrida(1, 0.006, -1) }, { "1000_20", Corrida(1,
				0.07, -1) }, { "1000_30", Corrida(1, 0.735, -1) }, { "1000_40",
				Corrida(1, 8.4, -1) }, { "1000_50", Corrida(1, 200, -1) }, {
				"5000_10", Corrida(1, 4.580, -1) }, { "5000_20", Corrida(1, 260,
				-1) }, { "10000_10", Corrida(1, 87.9, -1) }, { "15000_10",
				Corrida(1, 507, -1) } };

Corrida::Corrida(string datos) : Corrida() {
	accumulate(datos);
}

void Corrida::accumulate(string datos) {
	npruebas++;

	if (datos.empty())
		return;

	int initpos = datos.find_first_not_of(" \t");
	string datostr = datos.substr(initpos);
	datostr = datostr.substr(datostr.find(" "));
	datostr = datostr.substr(datostr.find_first_not_of(" \t"));
	renumbTime += atof(datostr.data());

	datostr = datostr.substr(datostr.find(" "));
	datostr = datostr.substr(datostr.find_first_not_of(" \t"));
	nsubp += atof(datostr.data());

	datostr = datostr.substr(datostr.find(" "));
	datostr = datostr.substr(datostr.find_first_not_of(" \t"));
	compTime += atof(datostr.data());
}

void Corrida::promedio() {
	if (npruebas <= 1)
		return;

	compTime /= npruebas;
	nsubp /= npruebas;
}

void Corrida::print(Instance graph, int K) {
	cout << "Nombre: " << graph.nombre << endl;
	cout << "Número de vertices: " << graph.tamanos.nvert << endl;
	cout << "Opcion = " << K << endl;
	cout << "Número de subproblemas: " << nsubp << endl;
	cout << "Time = " << compTime << endl;
}

void leerCorridasDimacs(string line, mapCorridas& corridas, set<int>& orders) {
	string graph = line.substr(
			line.substr(0, line.find_first_of(" ")).find_last_of("/") + 1);
	int pos = graph.find(".clq");
	graph = graph.substr(0, pos);
	string datos = line.substr(line.find_first_of(" "));
	pos = datos.find_first_not_of(" \t");
	datos = datos.substr(pos);

	Instance instance = { graph, conocidasDimacs.find(graph)->second };//, atoi(datos.data()) };

	datos = datos.substr(datos.find(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));
	int opcionHeur = atoi(datos.data());

	datos = datos.substr(datos.find(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));
	int opcionOrder = atoi(datos.data());

	orders.insert(opcionOrder);

	mapCorridas::iterator corrida;
	corrida = corridas.find(instance);
	if (corrida == corridas.end())
		corridas[instance] = vector < vector<Corrida> > (5);
	corridas[instance][opcionHeur].resize(5);
	corridas[instance][opcionHeur][opcionOrder] = Corrida(
			datos.substr(datos.find(" ")));
}

void leerCorridasRand(string line, mapCorridas& corridas, set<int>& orders) {
	string graph = line.substr(0, line.find_last_of("/"));
	graph = graph.substr(graph.find_last_of("/") + 1);
	string datos = line.substr(line.find_first_of(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));

	datos = datos.substr(datos.find(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));
	int opcionHeur = atoi(datos.data());

	datos = datos.substr(datos.find(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));
	int opcionOrder = atoi(datos.data());

	orders.insert(opcionOrder);

	datos = datos.substr(datos.find(" "));
	datos = datos.substr(datos.find_first_not_of(" \t"));

	double dens = atof(graph.substr(graph.find("_")+1).data());
	while (dens >= 1.0-1.0e-5)
		dens /= 10;
	Instance instance = { graph, { atoi(graph.data()), dens, atoi(datos.data()) } };

	mapCorridas::iterator corrida;
	corrida = corridas.find(instance);
	if (corrida == corridas.end()) {
		instance.tamanos.omegamax = instance.tamanos.omegamin;
		corridas[instance] = vector < vector<Corrida> > (5);
		corridas[instance][opcionHeur].resize(5);
		corridas[instance][opcionHeur][opcionOrder] = Corrida(datos);
//		corridas[instance][opcionHeur].print(instance,opcion);
	} else {
		corrida->second[opcionHeur].resize(5);
		corrida->second[opcionHeur][opcionOrder].accumulate(datos);
//		corrida->second[opcionHeur].print(instance,opcion);

		vector<vector<Corrida> > c(corrida->second);
		if (corrida->first.tamanos.omegamin < instance.tamanos.omegamin)
			instance.tamanos.omegamin = corrida->first.tamanos.omegamin;
		if (corrida->first.tamanos.omegamax > instance.tamanos.omegamax)
			instance.tamanos.omegamax = corrida->first.tamanos.omegamax;
		corridas.erase(corrida);
		corridas[instance] = c;
	}
}

int decimales(double v) {
	if (v < 1.0)
		return 3;
	if (v < 100)
		return 2;
	if (v < 1000)
		return 1;
	return 0;
}

int compare(double v1, double v2) {
	double epsilon = 0.01;
//	int i;
//	for (i = 0; i < decimales(v1); ++i)
//		epsilon *= 0.1;
	return (v1 == v2) || ((v1 <= v2 * (1 + epsilon) && v1 >= v2 * (1 - epsilon)));
}

string toString(double valor, bool bold = false, bool emph = false) {
	if (valor <= 0.00099)
		return "--";
	string valorstr = to_string(valor);
	int pointpos = valorstr.find_first_of('.');
	int dec = decimales(valor);
	if (dec > 0	&& valorstr.substr(pointpos + 1, pointpos + dec + 1).find_first_not_of('0') == string::npos)
		dec = 0;
	string ret(valorstr.substr(0, pointpos + dec + (dec == 0 ? 0 : 1)));
	if (bold)
		ret = "{\\bf " + ret + "}";
//	if (emph)
//		ret = "\\colorbox{yellow}{" + ret + "}";
	return ret;
}

typedef struct F {
	Instance	instancia;
	string *	fila;

	F(const Instance i, string f[]) : instancia(i), fila(f) {};
} FilasTabla;

void escribirTabla(mapCorridas& corridas_rd, mapCorridas& corridas_pb,
		mapCorridas& corridas_bb, set<int>& orders, list<FilasTabla>& filaTabla) {

	int iter = -1;
	string hline("\\hline\n");
	for (mapCorridas::iterator corrida_rd = corridas_rd.begin();
			corrida_rd != corridas_rd.end(); ++corrida_rd) {
		set<int>::iterator order;
		for (order = orders.begin(); order != orders.end(); ++order)
			if (corrida_rd->second[1][*order].compTime < 0.099) {
				break;
			}
		if (order != orders.end()) {
			continue;
		}

		string graphstr = corrida_rd->first.nombre;
		mapCorridas::iterator corrida_pb = corridas_pb.find(corrida_rd->first);

		if (corrida_pb == corridas_pb.end())
			continue;

		mapCorridas::iterator corrida_bb = corridas_bb.find(corrida_rd->first);

		if (corrida_bb == corridas_bb.end())
			continue;

		iter = (++iter % 2);

		string * filaGrafo = new string[4];
		int ifila = 0;

		for (order = orders.begin(); order != orders.end(); ++order) {
			double bestTime = corrida_rd->second[1][*order].compTime;
			double bestNSubp = corrida_rd->second[1][*order].nsubp;

			for (int K = 2; K < corrida_rd->second.size(); ++K)
				if (corrida_rd->second[K].size() > *order
						&& corrida_rd->second[K][*order].compTime > 0) {
					if (corrida_rd->second[K][*order].compTime < bestTime)
						bestTime = corrida_rd->second[K][*order].compTime;
					if (corrida_rd->second[K][*order].nsubp > 0
							&& corrida_rd->second[K][*order].nsubp < bestNSubp)
						bestNSubp = corrida_rd->second[K][*order].nsubp;
				}
			for (int K = 1; K < corrida_pb->second.size(); ++K)
				if (corrida_pb->second[K].size() > *order
						&& corrida_pb->second[K][*order].compTime > 0) {
					if (corrida_pb->second[K][*order].compTime < bestTime)
						bestTime = corrida_pb->second[K][*order].compTime;
					if (corrida_pb->second[K][*order].nsubp > 0
							&& corrida_pb->second[K][*order].nsubp < bestNSubp)
						bestNSubp = corrida_pb->second[K][*order].nsubp;
				}
			for (int K = 1; K < corrida_bb->second.size(); ++K)
				if (corrida_bb->second[K].size() > *order
						&& corrida_bb->second[K][*order].compTime > 0) {
					if (corrida_bb->second[K][*order].compTime < bestTime)
						bestTime = corrida_bb->second[K][*order].compTime;
					if (corrida_bb->second[K][*order].nsubp > 0
							&& corrida_bb->second[K][*order].nsubp < bestNSubp)
						bestNSubp = corrida_bb->second[K][*order].nsubp;
				}

			double tomitaTime = 0.0;
			double tomitaNSubp = 0.0;
			if (*order == 1 || *order == 2) {
				map<string, Corrida>::iterator ut = tomitaMCS.find(graphstr);
				if (ut != tomitaMCS.end()) {
					tomitaTime = ut->second.compTime * 1.09;
					if (ut->second.nsubp > 0)
						tomitaNSubp = ut->second.nsubp;
				}
			}

			double segundoJimenezTime = 0.0;
			double segundoJimenezNSubp = 0.0;
			if (*order == 3 || *order == 4) {
				map<string, Corrida>::iterator usj = segundoJimenez.find(
						graphstr);
				if (usj != segundoJimenez.end()) {
					segundoJimenezTime = usj->second.compTime * 1.61;
					if (usj->second.nsubp > 0)
						segundoJimenezNSubp = usj->second.nsubp;
				}
			}

			double segundoMatiaITime = 0.0;
			double segundoMatiaINSubp = 0.0;
			if (*order == 3 || *order == 4) {
				map<string, Corrida>::iterator usmi = segundoMatiaI.find(
						graphstr);
				if (usmi != segundoMatiaI.end()) {
					segundoMatiaITime = usmi->second.compTime * 1.98;
					if (usmi->second.nsubp > 0)
						segundoMatiaINSubp = usmi->second.nsubp;
				}
			}

			double segundoMatiaRTime = 0.0;
			double segundoMatiaRNSubp = 0.0;
			if (*order == 3 || *order == 4) {
				map<string, Corrida>::iterator usmr = segundoMatiaR.find(
						graphstr);
				if (usmr != segundoMatiaR.end()) {
					segundoMatiaRTime = usmr->second.compTime * 1.98;
					if (usmr->second.nsubp > 0)
						segundoMatiaRNSubp = usmr->second.nsubp;
				}
			}

			double boldTime = bestTime;
			if (tomitaTime > 0 && tomitaTime < boldTime)
				boldTime = tomitaTime;
			if (segundoJimenezTime > 0 && segundoJimenezTime < boldTime)
				boldTime = segundoJimenezTime;
			if (segundoMatiaITime > 0 && segundoMatiaITime < boldTime)
				boldTime = segundoMatiaITime;
			if (segundoMatiaRTime > 0 && segundoMatiaRTime < boldTime)
				boldTime = segundoMatiaRTime;

			double boldNSubp = bestNSubp;
			if (tomitaNSubp > 0 && tomitaNSubp < boldNSubp)
				boldNSubp = tomitaNSubp;
			if (segundoJimenezNSubp > 0 && segundoJimenezNSubp < boldNSubp)
				boldNSubp = segundoJimenezNSubp;
			if (segundoMatiaINSubp > 0 && segundoMatiaINSubp < boldNSubp)
				boldNSubp = segundoMatiaINSubp;
			if (segundoMatiaRNSubp > 0 && segundoMatiaRNSubp < boldNSubp)
				boldNSubp = segundoMatiaRNSubp;

			string literatNSubp;
			if (*order == 2)
				literatNSubp = toString(tomitaNSubp / 1000,
						compare(tomitaNSubp, boldNSubp));
			else if (*order == 3)
				literatNSubp = toString(segundoJimenezNSubp / 1000,
						compare(segundoJimenezNSubp, boldNSubp));
			else
				literatNSubp = toString(0);
			string literatTime;
			if (*order == 2)
				literatTime = toString(tomitaTime,
						compare(tomitaTime, boldTime));
			else if (*order == 3)
				literatTime = toString(segundoMatiaITime,
						compare(segundoMatiaITime, boldTime));
			else
				literatTime = toString(0);

			if (*order == 3)
				filaGrafo[ifila].append("*\n\\cline{2-5} \\cline{7-10}\n");
			else
				filaGrafo[ifila].append("\n");
			if (iter == 0)
				filaGrafo[ifila].append("\\rowcolor[gray]{.8} ");

			double nsubpbb = corrida_bb->second[1][*order].nsubp;
			double nsubppb = corrida_pb->second[1][*order].nsubp;
			double nsubprd = corrida_rd->second[1][*order].nsubp;

			double compTimebb = corrida_bb->second[1][*order].compTime;
			if (compTimebb > 7200)
			{
				compTimebb = -1;
				nsubpbb = -1;
			}
			double compTimepb = corrida_pb->second[1][*order].compTime;
			if (compTimepb > 7200)
			{
				compTimepb = -1;
				nsubppb = -1;
			}
			double compTimerd = corrida_rd->second[1][*order].compTime;
			if (compTimerd > 7200)
			{
				compTimerd = -1;
				nsubprd = -1;
			}

			filaGrafo[ifila].append(
					" & " + literatNSubp + " & "
							+ toString(nsubpbb / 1000, compare(nsubpbb, boldNSubp), compare(nsubpbb, bestNSubp)) + " & "
							+ toString(nsubppb / 1000, compare(nsubppb, boldNSubp), compare(nsubppb, bestNSubp)) + " & "
							+ toString(nsubprd / 1000, compare(nsubprd, boldNSubp), compare(nsubprd, bestNSubp)) + " & " + " & "
							 + literatTime + " & "
							+ toString(compTimebb, compare(compTimebb, boldTime), compare(compTimebb, bestTime)) + " & "
							+ toString(compTimepb, compare(compTimepb, boldTime), compare(compTimepb, bestTime)) + " & "
							+ toString(compTimerd, compare(compTimerd, boldTime), compare(compTimerd, bestTime)) + " \\\\* ");

			int p = -3;
			while ((p = filaGrafo[ifila].find_first_of('_', p + 3)) != string::npos)
				filaGrafo[ifila].insert(p, 1, '\\');

			filaGrafo[ifila].append("\n");

			ifila++;
			if (iter == 0)
				filaGrafo[ifila].append("\\rowcolor[gray]{.8} ");
			if (*order == 3)
				filaGrafo[ifila].append("\\multirow{-4}{*}{\\tt " + graphstr + "} ");

			nsubpbb = corrida_bb->second[2][*order].nsubp;
			nsubppb = corrida_pb->second[2][*order].nsubp;
			nsubprd = corrida_rd->second[2][*order].nsubp;

			compTimebb = corrida_bb->second[2][*order].compTime;
			if (compTimebb > 7200)
			{
				compTimebb = -1;
				nsubpbb = -1;
			}
			compTimepb = corrida_pb->second[2][*order].compTime;
			if (compTimepb > 7200)
			{
				compTimepb = -1;
				nsubppb = -1;
			}
			compTimerd = corrida_rd->second[2][*order].compTime;
			if (compTimerd > 7200)
			{
				compTimerd = -1;
				nsubprd = -1;
			}

			filaGrafo[ifila].append(
					" & & "
					+ toString(nsubpbb / 1000, compare(nsubpbb, boldNSubp), compare(nsubpbb, bestNSubp)) + " & "
					+ toString(nsubppb / 1000, compare(nsubppb, boldNSubp), compare(nsubppb, bestNSubp)) + " & "
					+ toString(nsubprd / 1000, compare(nsubprd, boldNSubp), compare(nsubprd, bestNSubp)) + " & "
							+ "\\multirow{-2}{*}{" + toString(corrida_rd->second[1][*order].renumbTime)
							+ "} & "
							+ toString(segundoMatiaRTime,
									compare(segundoMatiaRTime, boldTime))
							+ " & "
							+ toString(compTimebb, compare(compTimebb, boldTime), compare(compTimebb, bestTime)) + " & "
							+ toString(compTimepb, compare(compTimepb, boldTime), compare(compTimepb, bestTime)) + " & "
							+ toString(compTimerd, compare(compTimerd, boldTime), compare(compTimerd, bestTime)) + " \\\\");

			p = -3;
			while ((p = filaGrafo[ifila].find_first_of('_', p + 3)) != string::npos)
				filaGrafo[ifila].insert(p, 1, '\\');

			ifila++;
		}
		filaGrafo[--ifila].append("\n"+hline);
		filaTabla.push_back(FilasTabla(corrida_rd->first,filaGrafo));
	}
}

void exportTabla(list<FilasTabla>& filaTabla, string outname) {
	ofstream outStream(outname.data());

	char encabezado[] =
			"\\begin{tabular}{|c|cccc|c|cccc|} \\hline\
Instance & \\multicolumn{4}{|c|}{Number of subproblems $\\times 10^{-3}$} & Renumber & \\multicolumn{4}{|c|}{Time (seconds)}  \\\\ \
\\cline{2-5} \\cline{7-10} & \\cite{Segu11} 	& \\cite{Tomi10} 	&	{\\em BB} &	{\\em RD} &\
Time & \\cite{Segu13}    & \\cite{Tomi10} 	& {\\em BB} 	&	{\\em RD}    	\\\\ \
\\hline \\hline";

//	outStream.write(encabezado, strlen(encabezado));

	while (!filaTabla.empty())
	{
		FilasTabla f = filaTabla.front();
		filaTabla.pop_front();
		for (int i = 0; i < 4; ++i)
			outStream.write(f.fila[i].data(), strlen(f.fila[i].data()));
	}

	char acotacion[] = "\\hline\n\
\\end{tabular}";

//	outStream.write(acotacion, strlen(acotacion));

	outStream.close();
}

void exportGrafos(list<FilasTabla>& filaTabla, string outname) {
	ofstream outStream(outname.data());

	int size = filaTabla.size();
	int msize = size/2;
	for (list<FilasTabla>::iterator i = filaTabla.begin(); i != filaTabla.end(); ++i)
	{
		FilasTabla f = *i;
		string d(to_string(f.instancia.tamanos.dens+5.0e-04));
		string nm(f.instancia.nombre);
		int p = -3;
		while ((p = nm.find_first_of('_', p + 3)) != string::npos)
			nm.insert(p, 1, '\\');

		string fila("{\\tt " + nm + "} & " + to_string(f.instancia.tamanos.nvert) + " & " + d.substr(0,d.find_first_of('.')+4) + " & " + to_string(f.instancia.tamanos.omegamin));
		if (f.instancia.tamanos.omegamax > f.instancia.tamanos.omegamin)
			fila.append("--" + to_string(f.instancia.tamanos.omegamax));
		fila.append(" \\\\ \n");
		outStream.write(fila.data(), strlen(fila.data()));

		if (--size == msize)
			outStream.write("\n", strlen("\n"));
	}

	outStream.close();
}

void mapaPareja(mapCorridas::iterator& corrida, map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)>& mapGraficos)
{
	mapGraficos[corrida->first] = vector<vector<double> > (5);
	mapGraficos[corrida->first][1].resize(5);
	mapGraficos[corrida->first][2].resize(5);
	if (corrida->second[1][3].compTime >= corrida->second[1][2].compTime)
		mapGraficos[corrida->first][1][2] = corrida->second[1][3].compTime/corrida->second[1][2].compTime-1;
	else
		mapGraficos[corrida->first][1][2] = -corrida->second[1][2].compTime/corrida->second[1][3].compTime+1;
	if (corrida->second[2][3].compTime >= corrida->second[2][2].compTime)
		mapGraficos[corrida->first][2][2] = corrida->second[2][3].compTime/corrida->second[2][2].compTime-1;
	else
		mapGraficos[corrida->first][2][2] = -corrida->second[2][2].compTime/corrida->second[2][3].compTime+1;
	if (corrida->second[1][2].compTime >= corrida->second[2][2].compTime)
		mapGraficos[corrida->first][1][3] = corrida->second[1][2].compTime/corrida->second[2][2].compTime-1;
	else
		mapGraficos[corrida->first][1][3] = -corrida->second[2][2].compTime/corrida->second[1][2].compTime+1;
	if (corrida->second[1][3].compTime >= corrida->second[2][3].compTime)
		mapGraficos[corrida->first][2][3] = corrida->second[1][3].compTime/corrida->second[2][3].compTime-1;
	else
		mapGraficos[corrida->first][2][3] = -corrida->second[2][3].compTime/corrida->second[1][3].compTime+1;
}

void escribirMapa(map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)>& mapGraficos, string& outname)
{
	ofstream outStream(outname.data());

	int i = 0;
	for (map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)>::iterator corrida = mapGraficos.begin(); corrida != mapGraficos.end(); ++corrida)
	if (mapGraficos[corrida->first][1][2] <= 20 &&
			mapGraficos[corrida->first][1][3] <= 20 &&
			mapGraficos[corrida->first][2][2] <= 20 &&
			mapGraficos[corrida->first][2][3] <= 20 &&
			mapGraficos[corrida->first][1][2] >= -20 &&
						mapGraficos[corrida->first][1][3] >= -20 &&
						mapGraficos[corrida->first][2][2] >= -20 &&
						mapGraficos[corrida->first][2][3] >= -20)
	{
		++i;
		string filaGrafo("\""+corrida->first.nombre+"\"");
		filaGrafo.append(" \t ");
		filaGrafo.append(to_string(i));
		filaGrafo.append(" \t");
		filaGrafo.append(to_string(mapGraficos[corrida->first][1][2]*100)); // (1/4)/(1/3) o 1/3, columna 3
//		if (mapGraficos[corrida->first][1][2] > 0)
//			filaGrafo.append(to_string(log10(mapGraficos[corrida->first][1][2]*10))); // (1/4)/(1/3) o 1/3, columna 3
//		else
//			filaGrafo.append(to_string(-log10(-mapGraficos[corrida->first][1][2]*10))); // (1/4)/(1/3) o 1/3, columna 3
		filaGrafo.append(" \t");
		filaGrafo.append(to_string(mapGraficos[corrida->first][1][3]*100)); // (1/3)/(2/3) o 1/4, columna 4
//		if (mapGraficos[corrida->first][1][3] > 0)
//			filaGrafo.append(to_string(log10(mapGraficos[corrida->first][1][3]*10))); // (1/3)/(2/3) o 1/4, columna 4
//		else
//			filaGrafo.append(to_string(-log10(-mapGraficos[corrida->first][1][3]*10))); // (1/3)/(2/3) o 1/4, columna 4
		filaGrafo.append(" \t");
		filaGrafo.append(to_string(mapGraficos[corrida->first][2][2]*100)); // (2/4)/(2/3) o 2/3, columna 5
//		if (mapGraficos[corrida->first][2][2] > 0)
//			filaGrafo.append(to_string(log10(mapGraficos[corrida->first][2][2]*10))); // (2/4)/(2/3) o 2/3, columna 5
//		else
//			filaGrafo.append(to_string(-log10(-mapGraficos[corrida->first][2][2]*10))); // (2/4)/(2/3) o 2/3, columna 5
		filaGrafo.append(" \t");
		filaGrafo.append(to_string(mapGraficos[corrida->first][2][3]*100)); // (1/4)/(2/4) o 2/4, columna 6
//		if (mapGraficos[corrida->first][2][3] > 0)
//			filaGrafo.append(to_string(log10(mapGraficos[corrida->first][2][3]*10))); // (1/4)/(2/4) o 2/4, columna 6
//		else
//			filaGrafo.append(to_string(-log10(-mapGraficos[corrida->first][2][3]*10))); // (1/4)/(2/4) o 2/4, columna 6
		filaGrafo.append(" \t");
		if (i % 5 == 0) {
			int d = 1000*(corrida->first.tamanos.dens+1.0e-4);
			if (d % 10 == 0)
				filaGrafo.append(to_string(d/10));
			else {
				char buffer[10];
				sprintf(buffer,"%3.1f", 100*corrida->first.tamanos.dens);
				filaGrafo.append(buffer);
			}
		}
		filaGrafo.append("\n");
		outStream.write(filaGrafo.data(), filaGrafo.length());
	}

	outStream.close();
}

void escribirGraficoMismoAlgo(mapCorridas& corridasDimacs, mapCorridas& corridasRand, string outname) {
	ofstream outStream(outname.data());
	bool (*fn_pt)(Instance, Instance) = dimacsDensComp;
	map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)> mapGraficos(fn_pt);
	for (mapCorridas::iterator corrida = corridasDimacs.begin(); corrida != corridasDimacs.end(); ++corrida) {
		if (corrida->second[1][2].compTime > 0.099 && corrida->second[1][3].compTime > 0.099)
			mapaPareja(corrida, mapGraficos);
	}
	for (mapCorridas::iterator corrida = corridasRand.begin(); corrida != corridasRand.end(); ++corrida) {
		if (corrida->second[1][2].compTime > 0.099 && corrida->second[1][3].compTime > 0.099)
			mapaPareja(corrida, mapGraficos);
	}
	escribirMapa(mapGraficos, outname);
}

void mapaParejaPareja(mapCorridas::iterator& corrida1, mapCorridas::iterator& corrida2, map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)>& mapGraficos)
{
	mapGraficos[corrida2->first] = vector<vector<double> > (5);
	mapGraficos[corrida2->first][1].resize(5);
	double f = corrida1->second[1][2].compTime;
	if (f == 0)
		f = 7200;
	if (f >= corrida2->second[1][2].compTime)
		mapGraficos[corrida2->first][1][2] = f/corrida2->second[1][2].compTime-1;
	else
		mapGraficos[corrida2->first][1][2] = -corrida2->second[1][2].compTime/f+1;
	f = corrida1->second[1][3].compTime;
	if (f == 0)
		f = 7200;
	if (f >= corrida2->second[1][3].compTime)
		mapGraficos[corrida2->first][1][3] = f/corrida2->second[1][3].compTime-1;
	else
		mapGraficos[corrida2->first][1][3] = -corrida2->second[1][3].compTime/f+1;
	mapGraficos[corrida2->first][2].resize(5);
	f = corrida1->second[2][2].compTime;
	if (f == 0)
		f = 7200;
	if (f >= corrida2->second[2][2].compTime)
		mapGraficos[corrida2->first][2][2] = f/corrida2->second[2][2].compTime-1;
	else
		mapGraficos[corrida2->first][2][2] = -corrida2->second[2][2].compTime/f+1;
	f = corrida1->second[2][3].compTime;
	if (f == 0)
		f = 7200;
	if (f >= corrida2->second[2][3].compTime)
		mapGraficos[corrida2->first][2][3] = f/corrida2->second[2][3].compTime-1;
	else
		mapGraficos[corrida2->first][2][3] = -corrida2->second[2][3].compTime/f+1;
}

void escribirGraficoDosAlgos(mapCorridas& corridasDimacs1, mapCorridas& corridasRand1, mapCorridas& corridasDimacs2, mapCorridas& corridasRand2, string outname) {
	bool (*fn_pt)(Instance, Instance) = dimacsDensComp;
	map<Instance, vector<vector<double> >, bool (*)(Instance, Instance)> mapGraficos(fn_pt);
	for (mapCorridas::iterator corrida2 = corridasDimacs2.begin(); corrida2 != corridasDimacs2.end(); ++corrida2) {
		cout << corrida2->first.nombre << endl;
		mapCorridas::iterator corrida1 = corridasDimacs1.find(corrida2->first);
		if (corrida1 != corridasDimacs1.end() && corrida1->second[1][2].compTime > 0.099 && corrida1->second[1][3].compTime > 0.099)
		{
			cout << corrida1->first.nombre << endl;
			mapaParejaPareja(corrida1, corrida2, mapGraficos);
		}
	}
	for (mapCorridas::iterator corrida2 = corridasRand2.begin(); corrida2 != corridasRand2.end(); ++corrida2) {
		cout << corrida2->first.nombre << endl;
		mapCorridas::iterator corrida1 = corridasRand1.find(corrida2->first);
		if (corrida1 != corridasRand1.end() && corrida1->second[1][2].compTime > 0.099 && corrida1->second[1][3].compTime > 0.099)
		{
			cout << corrida1->first.nombre << endl;
			mapaParejaPareja(corrida1, corrida2, mapGraficos);
		}
	}
	escribirMapa(mapGraficos, outname);
}

int main(int argc, char *argv[]) {

	if (argc < 4) {
		cout
				<< "Llamada: cosecha <archivo datos rd> <archivo datos pb> <archivo datos bb> <archivo salida>\n";
		exit(0);
	}

	string filename_rd(argv[1]), filename_pb(argv[2]), filename_bb(argv[3]);
	cout << filename_rd << " " << filename_pb << filename_bb << endl;

	bool (*fn_pt)(Instance, Instance) = dimacsNombreComp;
	mapCorridas corridasDimacs_rd(fn_pt);
	mapCorridas corridasDimacs_bb(fn_pt);
	mapCorridas corridasDimacs_pb(fn_pt);

	fn_pt = randNombreComp;
	mapCorridas corridasRand_rd(fn_pt);
	mapCorridas corridasRand_bb(fn_pt);
	mapCorridas corridasRand_pb(fn_pt);

	set<int> ordersDimacs;
	set<int> ordersRand;

	ifstream corridasStream_rd(filename_rd.data());
	string line;
	while (getline(corridasStream_rd, line)) {
		cout << line << endl;
		if (line.find("dimacs") != string::npos || line.find("frb30-15") != string::npos)
			leerCorridasDimacs(line, corridasDimacs_rd, ordersDimacs);
		else if (line.find("random") != string::npos)
			leerCorridasRand(line, corridasRand_rd, ordersRand);
		else
			cout << "Fila desconocida encontrada: " << line << endl;
	}
	corridasStream_rd.close();

	ifstream corridasStream_pb(filename_pb.data());
	while (getline(corridasStream_pb, line)) {
		cout << line << endl;
		if (line.find("dimacs") != string::npos || line.find("frb30-15") != string::npos)
			leerCorridasDimacs(line, corridasDimacs_pb, ordersDimacs);
		else if (line.find("random") != string::npos)
			leerCorridasRand(line, corridasRand_pb, ordersRand);
		else
			cout << "Fila desconocida encontrada: " << line << endl;
	}
	corridasStream_pb.close();

	ifstream corridasStream_bb(filename_bb.data());
	while (getline(corridasStream_bb, line)) {
		cout << line << endl;
		if (line.find("dimacs") != string::npos || line.find("frb30-15") != string::npos)
			leerCorridasDimacs(line, corridasDimacs_bb, ordersDimacs);
		else if (line.find("random") != string::npos)
			leerCorridasRand(line, corridasRand_bb, ordersRand);
		else
			cout << "Fila desconocida encontrada: " << line << endl;
	}
	corridasStream_bb.close();

	list<FilasTabla> filasDimacs;
	escribirTabla(corridasDimacs_rd, corridasDimacs_pb, corridasDimacs_bb,
			ordersDimacs, filasDimacs);

	for (mapCorridas::iterator corrida = corridasRand_rd.begin();
			corrida != corridasRand_rd.end(); ++corrida) {
		for (int i = 1; i < corrida->second.size(); ++i)
			for (set<int>::iterator order = ordersDimacs.begin();
					order != ordersDimacs.end(); ++order)
				if (corrida->second[i].size() > *order)
					corrida->second[i][*order].promedio();
	}
	for (mapCorridas::iterator corrida = corridasRand_pb.begin();
			corrida != corridasRand_pb.end(); ++corrida) {
		for (int i = 1; i < corrida->second.size(); ++i)
			for (set<int>::iterator order = ordersRand.begin();
					order != ordersRand.end(); ++order)
				if (corrida->second[i].size() > *order)
					corrida->second[i][*order].promedio();
	}
	for (mapCorridas::iterator corrida = corridasRand_bb.begin();
			corrida != corridasRand_bb.end(); ++corrida) {
		for (int i = 1; i < corrida->second.size(); ++i)
			for (set<int>::iterator order = ordersRand.begin();
					order != ordersRand.end(); ++order)
				if (corrida->second[i].size() > *order)
					corrida->second[i][*order].promedio();
	}
	list<FilasTabla> filasRand;
	escribirTabla(corridasRand_rd, corridasRand_pb, corridasRand_bb, ordersRand, filasRand);

	exportGrafos(filasDimacs, string(argv[4]) + "-grafos-dimacs.tex");
	exportGrafos(filasRand, string(argv[4]) + "-grafos-rand.tex");

	exportTabla(filasDimacs, string(argv[4]) + "-dimacs.tex");
	exportTabla(filasRand, string(argv[4]) + "-rand.tex");

	escribirGraficoMismoAlgo(corridasDimacs_bb, corridasRand_bb, string(argv[4]) + "-plot-bb.dat");
	escribirGraficoMismoAlgo(corridasDimacs_pb, corridasRand_pb, string(argv[4]) + "-plot-pb.dat");
	escribirGraficoMismoAlgo(corridasDimacs_rd, corridasRand_rd, string(argv[4]) + "-plot-rd.dat");

	escribirGraficoDosAlgos(corridasDimacs_bb, corridasRand_bb, corridasDimacs_pb, corridasRand_pb, string(argv[4]) + "-plot-pb-bb.dat");
	escribirGraficoDosAlgos(corridasDimacs_bb, corridasRand_bb, corridasDimacs_rd, corridasRand_rd, string(argv[4]) + "-plot-rd-bb.dat");
	escribirGraficoDosAlgos(corridasDimacs_pb, corridasRand_pb, corridasDimacs_rd, corridasRand_rd, string(argv[4]) + "-plot-rd-pb.dat");

	corridasDimacs_rd.clear();
	corridasDimacs_pb.clear();
	corridasDimacs_bb.clear();

	corridasRand_rd.clear();
	corridasRand_pb.clear();
	corridasRand_bb.clear();
}
